package com.example.yan_music.test.widge;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.yan_music.R;

/**
 * <p>
 *     圆形可滑动菜单布局
 * <p/>
 *
 */
public class CircleMenuLayout extends ViewGroup {
    private static final String TAG = "CircleMenuLayout";

    /**
     * 圆形菜单的半径
     */
    private int mRadius;

    /**
     * 该容器内child item的默认尺寸
     */
    private static final float DEFAULT_CHILD_SIZE = 1 / 4f;

    /**
     * 菜单的中心child的默认尺寸
     */
    private float DEFAULT_CENTER_ITEM_SIZE = 1 / 3f;

    /**
     * 该容器的内边距,无视padding属性，如需边距请用该变量
     */
    private static final float PADDING_LAYOUT = 1 / 12f;

    /**
     * 当每秒移动角度达到该值时，认为是快速移动
     */
    private static final int FAST_FLING_VALUE = 300;

    /**
     * 如果移动角度达到该值，则屏蔽点击
     */
    private static final int NOCLICK_VALUE = 3;

    /**
     * 当每秒移动角度达到该值时，认为是快速移动
     */
    private int mFastFlingValue = FAST_FLING_VALUE;

    /**
     * 该容器的内边距,无视padding属性，如需边距请用该变量
     */
    private float mPadding;

    /**
     * 布局时的开始角度
     */
    private double mStartAngle = 0;

    /**
     * 菜单项的文本
     */
    private String[] mItemText;

    /**
     * 菜单项的图标资源
     */
    private int[] mItemImgRes;
    /**
     * MenuItem的点击事件接口
     */
    private OnMenuItemClickListener mOnMenuItemClickListener;

    /**
     * 菜单的个数
     */
    private int mMenuItemCount;

    /**
     * 检测按下到抬起时旋转的角度，也就是一次动作运行的角度
     */
    private float mSingleActionAngle;

    /**
     * 检测按下到抬起时使用的时间，也就是一次动作花费的时间
     */
    private long mSingleActionTime;

    /**
     * 判断是否正在自动滚动
     */
    private boolean isAutoFling;

    /**
     * 菜单子项item的布局文件id
     */
    private int mMenuItemLayoutId = R.layout.circle_menu_item;


    public CircleMenuLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 无视padding
        setPadding(0, 0, 0, 0);
    }

    /**
     * 重写 onMesure() 方法
     * 测量布局大小
     *
     * @param widthMeasureSpec  控件可获得的空间宽度
     * @param heightMeasureSpec 控件可获得的控件高度
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int resWidth = 0;
        int resHeight = 0;

        /**
         * 根据传入的参数，分别获取测量模式和测量值
         */
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        /**
         * 如果宽或者高的测量模式非精确值(非MeasureSpec.EXACTLY，非充满父布局)
         */
        if (widthMode != MeasureSpec.EXACTLY
                || heightMode != MeasureSpec.EXACTLY) {
            // 主要设置为背景图的宽度（没有设置背景时返回值为0）
            resWidth = getSuggestedMinimumWidth();
            // 如果未设置背景图片，则设置为屏幕宽高的默认值
            resWidth = resWidth == 0 ? getDefaultWidth() : resWidth;

            resHeight = getSuggestedMinimumHeight();
            // 如果未设置背景图片，则设置为屏幕宽高的默认值
            resHeight = resHeight == 0 ? getDefaultWidth() : resHeight;
        } else {
            // 如果都设置为精确值，则直接取小值；
            resWidth = resHeight = Math.min(width, height);
        }

        // 设置控件的大小
        setMeasuredDimension(resWidth, resHeight);

        // 获得半径
        mRadius = Math.max(getMeasuredWidth(), getMeasuredHeight());

        // menu item数量
        final int childCount = getChildCount();
        // menu item尺寸
        int childSize = (int) (mRadius * DEFAULT_CHILD_SIZE);
        // menu item测量模式（精确值模式match）
        int childMode = MeasureSpec.EXACTLY;

        // 迭代测量
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }

            // 计算menu item的尺寸；以及和设置好的模式，去对item进行测量
            int makeMeasureSpec = -1;
            // 首先判断最中间的child
            if (child.getId() == R.id.id_circle_menu_item_center) {
                // 为最中间的child创建中间的测量值
                makeMeasureSpec = MeasureSpec.makeMeasureSpec(
                        (int) (mRadius * DEFAULT_CENTER_ITEM_SIZE),
                        childMode);
            } else {
                // 其余子项创建子项的测量值
                makeMeasureSpec = MeasureSpec.makeMeasureSpec(childSize,
                        childMode);
            }
            child.measure(makeMeasureSpec, makeMeasureSpec);
        }

        mPadding = PADDING_LAYOUT * mRadius;

    }

    /**
     * 菜单子项的点击接口
     */
    public interface OnMenuItemClickListener {

        /**
         * 非中间子项点击
         *
         * @param view
         * @param pos   点击位置
         */
        void onItemClick(View view, int pos);
        /**
         * 中间子项点击
         *
         * @param view
         */
        void onItemCenterClick(View view);

    }

    /**
     * 设置MenuItem的点击事件接口
     *
     * @param mOnMenuItemClickListener
     */
    public void setOnMenuItemClickListener(OnMenuItemClickListener mOnMenuItemClickListener) {
        this.mOnMenuItemClickListener = mOnMenuItemClickListener;
    }

    /**
     * 重写 onLayout() 方法
     * mesure结束后开始layout，确定视图位置
     *
     * @param changed
     * @param l         左
     * @param t         上
     * @param r         右
     * @param b         下
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 布局半径大小
        int layoutRadius = mRadius;

        // 获取待布局子项数目
        final int childCount = getChildCount();
        Log.d(TAG, "onLayout: " + "待布局子项数目：" + childCount);

        int left, top;

        // menu item 的尺寸
        int childWidth = (int) (layoutRadius * DEFAULT_CHILD_SIZE);

        float angleDelay = 0;

        if((getChildCount() - 1) != 0) {
            // 根据menu item的个数，计算角度
            // getChildCount() - 1 是去掉最中间的子项
            angleDelay = 360 / (getChildCount() - 1);
        }

        // 遍历去设置子项的位置
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            if (child.getId() == R.id.id_circle_menu_item_center) {
                continue;
            }

            if (child.getVisibility() == GONE) {
                continue;
            }

            // 初始角度，一开始为0
            mStartAngle %= 360;
            Log.d(TAG, "onLayout: " + "初始角度mStartAngle == " + mStartAngle);

            // 计算，中心点到menu item中心的距离
            float tmp = layoutRadius / 2f - childWidth / 2 - mPadding;

            // tmp cosa 即menu item中心点的横坐标
            /*
                     /丨
                   /  丨
                 / ___丨
             */
            left = layoutRadius
                    / 2
                    + (int) Math.round(tmp
                    * Math.cos(Math.toRadians(mStartAngle)) - 1 / 2f
                    * childWidth);
            // tmp sina 即menu item的纵坐标
            top = layoutRadius
                    / 2
                    + (int) Math.round(tmp
                    * Math.sin(Math.toRadians(mStartAngle)) - 1 / 2f
                    * childWidth);

            child.layout(left, top, left + childWidth, top + childWidth);
            // 叠加尺寸
            mStartAngle += angleDelay;
        }

        // 找到中心的view，如果存在则设置onclick事件
        View centerView = findViewById(R.id.id_circle_menu_item_center);
        if (centerView != null) {
            centerView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnMenuItemClickListener != null) {
                        mOnMenuItemClickListener.onItemCenterClick(v);
                        // 菜单显示 or 隐藏
                        for(int i = 1; i < childCount; i++){
                            final View child = getChildAt(i);
                            if(child.getVisibility() == View.VISIBLE) {
                                // 用 ViewPropertyAnimator 比较方便
                                child.animate().alpha(0).scaleX(0).scaleY(0)
                                        .setListener(new Animator.AnimatorListener() {
                                            @Override
                                            public void onAnimationStart(Animator animation) {

                                            }

                                            @Override
                                            public void onAnimationEnd(Animator animation) {
                                                child.setVisibility(View.GONE);
                                            }

                                            @Override
                                            public void onAnimationCancel(Animator animation) {

                                            }

                                            @Override
                                            public void onAnimationRepeat(Animator animation) {

                                            }
                                        })
                                        .setDuration(300);
                            }else {
                                child.animate().alpha(1).scaleX(1).scaleY(1)
                                        .setListener(new Animator.AnimatorListener() {
                                            @Override
                                            public void onAnimationStart(Animator animation) {
                                                child.setVisibility(View.VISIBLE);
                                            }

                                            @Override
                                            public void onAnimationEnd(Animator animation) {

                                            }

                                            @Override
                                            public void onAnimationCancel(Animator animation) {

                                            }

                                            @Override
                                            public void onAnimationRepeat(Animator animation) {

                                            }
                                        })
                                        .setDuration(300);
                            }
//                            if(child.getVisibility() == View.VISIBLE) {
////                                ViewPropertyAnimator animator3 = child.animate();
////                                animator3.alpha(0).scaleX(0).scaleY(0);
////                                animator3.setDuration(500);
////                                Log.d(TAG, "onClick: " + "子项可见");
////                                ObjectAnimator animator = ObjectAnimator.ofFloat(child, "alpha", 1, 0);
////                                ObjectAnimator animator1 = ObjectAnimator.ofFloat(child, "scaleX", 1, 0);
////                                ObjectAnimator animator2 = ObjectAnimator.ofFloat(child, "scaleY", 1, 0);
////                                AnimatorSet animatorSet = new AnimatorSet();
////                                animatorSet.playTogether(animator1, animator2, animator);
////                                animatorSet.setDuration(500);
////                                animator.addListener(new Animator.AnimatorListener() {
////                                    @Override
////                                    public void onAnimationStart(Animator animation) {
////
////                                    }
////
////                                    @Override
////                                    public void onAnimationEnd(Animator animation) {
////                                        child.setVisibility(View.GONE);
////                                    }
////
////                                    @Override
////                                    public void onAnimationCancel(Animator animation) {
////
////                                    }
////
////                                    @Override
////                                    public void onAnimationRepeat(Animator animation) {
////
////                                    }
////                                });
////                                animatorSet.start();
//                            }else {
//                                Log.d(TAG, "onClick: " + "子项不可见");
//                                ObjectAnimator animator = ObjectAnimator.ofFloat(child, "alpha", 0, 1);
//                                ObjectAnimator animator1 = ObjectAnimator.ofFloat(child, "scaleX", 0, 1);
//                                ObjectAnimator animator2 = ObjectAnimator.ofFloat(child, "scaleY", 0, 1);
//                                AnimatorSet animatorSet = new AnimatorSet();
//                                animatorSet.playTogether(animator1, animator2, animator);
//                                animatorSet.setDuration(500);
//                                animator.addListener(new Animator.AnimatorListener() {
//                                    @Override
//                                    public void onAnimationStart(Animator animation) {
//                                        child.setVisibility(View.VISIBLE);
//                                    }
//
//                                    @Override
//                                    public void onAnimationEnd(Animator animation) {
//
//                                    }
//
//                                    @Override
//                                    public void onAnimationCancel(Animator animation) {
//
//                                    }
//
//                                    @Override
//                                    public void onAnimationRepeat(Animator animation) {
//
//                                    }
//                                });
//                                animatorSet.start();
//
                        }
                    }
                }
            });
            // 设置center item位置
            int centerLeft = layoutRadius / 2 - centerView.getMeasuredWidth() / 2;
            int centerRight = centerLeft + centerView.getMeasuredWidth();
            // 让其居中
            centerView.layout(centerLeft, centerLeft, centerRight, centerRight);
        }

    }

    /**
     * 记录上一次的x，y坐标
     */
    private float mLastX;
    private float mLastY;

    /**
     * 自动滚动的Runnable
     */
    private AutoFlingRunnable mFlingRunnable;

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                mLastX = x;
                mLastY = y;
                mSingleActionTime = System.currentTimeMillis();
                mSingleActionAngle = 0;
                // 如果当前已经在快速滚动
                if (isAutoFling) {
                    // 移除快速滚动的回调
                    removeCallbacks(mFlingRunnable);
                    isAutoFling = false;
                    return true;
                }
                break;

            case MotionEvent.ACTION_MOVE:
                // 获得开始的角度
                float start = getAngle(mLastX, mLastY);
                //获得当前的角度
                float end = getAngle(x, y);
                // 如果是一、四象限，则直接end-start，角度值都是正值
                if (getQuadrant(x, y) == 1 || getQuadrant(x, y) == 4) {
                    mStartAngle += end - start;
                    mSingleActionAngle += end - start;
                } else {
                    // 二、三象限，角度值是付值
                    mStartAngle += start - end;
                    mSingleActionAngle += start - end;
                }
                // 重新布局
                requestLayout();
                mLastX = x;
                mLastY = y;
                break;

            case MotionEvent.ACTION_UP:
                // 计算，每秒移动的角度
                float anglePerSecond = mSingleActionAngle * 1000
                        / (System.currentTimeMillis() - mSingleActionTime);

                // Log.e("TAG", anglePrMillionSecond + " , mTmpAngel = " +
                // mTmpAngle);

                // 如果达到该值认为是快速移动
                if (Math.abs(anglePerSecond) > mFastFlingValue && !isAutoFling) {
                    // post一个任务，去自动滚动
                    post(mFlingRunnable = new AutoFlingRunnable(anglePerSecond));

                    return true;
                }

                // 如果当前旋转角度超过NOCLICK_VALUE屏蔽点击
                if (Math.abs(mSingleActionAngle) > NOCLICK_VALUE) {
                    return true;
                }

                break;
        }
        return super.dispatchTouchEvent(event);
    }

    /**
     * 主要为了action_down时，返回true
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return true;
    }

    /**
     * 根据触摸的位置，计算角度
     *
     * @param xTouch
     * @param yTouch
     * @return
     */
    private float getAngle(float xTouch, float yTouch) {
        double x = xTouch - (mRadius / 2d);
        double y = yTouch - (mRadius / 2d);
        return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
    }

    /**
     * 根据当前位置计算象限
     *
     * @param x
     * @param y
     * @return
     */
    private int getQuadrant(float x, float y) {
        int tmpX = (int) (x - mRadius / 2);
        int tmpY = (int) (y - mRadius / 2);
        if (tmpX >= 0) {
            return tmpY >= 0 ? 4 : 1;
        } else {
            return tmpY >= 0 ? 3 : 2;
        }

    }

    /**
     * 设置菜单图标和对应的标题
     *
     * @param resIds    图标资源数组
     * @param texts     标题数组
     */
    public void setMenuItemIconsAndTexts(int[] resIds, String[] texts) {
        // 参数检查
        if (resIds == null && texts == null) {
            throw new IllegalArgumentException("菜单项文本和图片至少一个");
        }

        mItemImgRes = resIds;
        mItemText = texts;

        // 初始化mMenuCount
        mMenuItemCount = resIds == null ? texts.length : resIds.length;

        if (resIds != null && texts != null) {
            mMenuItemCount = Math.min(resIds.length, texts.length);
        }

        addMenuItems();

    }

    /**
     * 设置MenuItem的布局文件，必须在setMenuItemIconsAndTexts之前调用
     *
     * @param mMenuItemLayoutId
     */
    public void setMenuItemLayoutId(int mMenuItemLayoutId) {
        this.mMenuItemLayoutId = mMenuItemLayoutId;
    }

    /**
     * 添加菜单子项
     */
    private void addMenuItems() {
        LayoutInflater mInflater = LayoutInflater.from(getContext());

        /**
         * 根据用户设置的参数，初始化view
         */
        for (int i = 0; i < mMenuItemCount; i++) {
            final int j = i;
            View view = mInflater.inflate(mMenuItemLayoutId, this, false);
            ImageView iv = (ImageView) view
                    .findViewById(R.id.id_circle_menu_item_image);
            TextView tv = (TextView) view
                    .findViewById(R.id.id_circle_menu_item_text);

            if (iv != null) {
                iv.setVisibility(View.VISIBLE);
                iv.setImageResource(mItemImgRes[i]);
                iv.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mOnMenuItemClickListener != null)
                        {
                            mOnMenuItemClickListener.onItemClick(v, j);
                        }
                    }
                });
            }
            if (tv != null) {
                tv.setVisibility(View.VISIBLE);
                tv.setText(mItemText[i]);
            }

            // 添加view到容器中
            addView(view);
        }
    }

    /**
     * 如果每秒旋转角度到达该值，则认为是自动滚动
     *
     * @param mFlingableValue
     */
    public void setFlingableValue(int mFlingableValue) {
        this.mFastFlingValue = mFlingableValue;
    }

    /**
     * 设置内边距的比例
     *
     * @param mPadding
     */
    public void setPadding(float mPadding)
    {
        this.mPadding = mPadding;
    }

    /**
     * 获得默认该layout的尺寸
     *
     * @return
     */
    private int getDefaultWidth() {
        WindowManager wm = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return Math.min(outMetrics.widthPixels, outMetrics.heightPixels);
    }

    /**
     * 自动滑动线程
     */
    private class AutoFlingRunnable implements Runnable {
        /**
         * 每秒对应的角度
         */
        private float angelPerSecond;

        public AutoFlingRunnable(float velocity)
        {
            this.angelPerSecond = velocity;
        }

        @Override
        public void run() {
            // 如果小于20,则停止
            if ((int) Math.abs(angelPerSecond) < 20)
            {
                isAutoFling = false;
                return;
            }
            isAutoFling = true;
            // 不断改变mStartAngle，让其滚动，/30为了避免滚动太快
            mStartAngle += (angelPerSecond / 30);
            // 逐渐减小这个值
            angelPerSecond /= 1.0666F;
            postDelayed(this, 30);
            // 重新布局
            requestLayout();
        }
    }

}


